package com.zut.blocks.service.course.impl;

import com.zut.blocks.base.common.request.CourseRequest;
import com.zut.blocks.base.common.request.GradeRequest;
import com.zut.blocks.base.common.request.StudentRequest;
import com.zut.blocks.base.domain.Course;
import com.zut.blocks.base.domain.Group;
import com.zut.blocks.base.domain.GroupStudent;
import com.zut.blocks.base.domain.User;
import com.zut.blocks.base.util.CheckUtil;
import com.zut.blocks.base.util.UserUtil;
import com.zut.blocks.dao.course.CourseRepository;
import com.zut.blocks.dao.group.GroupRepository;
import com.zut.blocks.dao.group.student.GroupStudentRepository;
import com.zut.blocks.dao.user.UserRepository;
import com.zut.blocks.service.course.CourseService;
import com.zut.blocks.service.course.vo.Student;
import com.zut.blocks.service.course.vo.StudentCourseGroup;
import com.zut.blocks.service.grade.GradeService;
import com.zut.blocks.service.grade.vo.FinalGrade;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author tianwei
 */
@Service
public class CourseServiceImpl implements CourseService {

    @Resource
    CourseRepository courseRepository;

    @Resource
    GroupStudentRepository groupStudentRepository;

    @Resource
    UserRepository userRepository;

    @Resource
    GroupRepository groupRepository;

    @Resource
    GradeService gradeService;

    Function<User, Student> mapToStudent = user -> {
        Student s = new Student();
        s.setId(user.getId());
        s.setStudentNum(user.getUserNumber());
        s.setName(user.getName());
        s.setGender(user.getGender());
        return s;
    };

    @Override
    public List<Course> findAll() {
        return courseRepository.findAll();
    }



    @Override
    public void group(String courseName) {

//        return courseRepository.save(Course c);
    }

    @Override
    public Integer delete(Integer courseID ) {
        courseRepository.deleteById(courseID);
        return courseID;
    }

    @Override
    public void change(String courseName) {

    }



    @Override
    public void save(String teacherName, String courseName) {
        Course c = new Course();
        c.setTeacherName(teacherName);
        c.setCourseName(courseName);


        courseRepository.save(c);


    }

    @Override
    public Page<Course> find(CourseRequest courseRequest) {
        return courseRepository.findByTeacherId(UserUtil.getUser().getId(), courseRequest.pageable(true));
    }

    @Override
    public List<Student> findCourseStudent(StudentRequest request) {
        Integer courseId = request.getCourseId();
        Assert.notNull(courseId, "course id 不能为空");
        List<GroupStudent> groupStudent = groupStudentRepository.findAllByCourseId(courseId);
        List<Integer> studentIds = groupStudent.stream().map(GroupStudent::getStudentId).collect(Collectors.toList());
        List<User> users = userRepository.findAllById(studentIds);

        GradeRequest gradeRequest = new GradeRequest();
        gradeRequest.setCourseId(request.getCourseId());
        List<FinalGrade> finalGradeByCourseId = gradeService.getFinalGradeByCourseId(gradeRequest);
        Map<Integer, Double> finalGradeMap = finalGradeByCourseId.stream()
                .collect(Collectors.toMap(FinalGrade::getId, FinalGrade::getFinalGrade));

        return users.stream().map(mapToStudent).peek(s -> {
            s.setFinalGrade(finalGradeMap.getOrDefault(s.getId(), null));
        }).collect(Collectors.toList());
    }

    @Override
    public Course findCourse(Integer courseId) {
        return courseRepository.findById(courseId).orElseGet(null);
    }

    @Override
    public Course add(Course course) {
        CheckUtil.notEmpty(course.getCourseName(), "课程名不能为空");
        Course save = new Course();
        save.setTeacherId(UserUtil.getUser().getId());
        save.setTeacherName(UserUtil.getUser().getName());
        save.setCourseName(course.getCourseName());
        save.setCreateTime(new Date());
        save.setCourseDescription(course.getCourseDescription());
        courseRepository.save(save);
        return save;
    }

    @Override
    public List<StudentCourseGroup> findAllByCourseId(Integer courseId) {
        Assert.notNull(courseId, "course id 不能为空");

        List<GroupStudent> allByCourseId = groupStudentRepository.findAllByCourseId(courseId);
        List<Integer> studentid = new ArrayList<>();
        Set<Integer> groupid = new HashSet<>();
        for (GroupStudent groupStudent : allByCourseId) {
            studentid.add(groupStudent.getStudentId());
            groupid.add(groupStudent.getGroupId());
        }

        List<User> users = userRepository.findAllById(studentid);
        List<Group> groups = groupRepository.findAllById(groupid);

        Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));
        Map<Integer, Group> groupMap = groups.stream().collect(Collectors.toMap(Group::getId, group -> group));

        List<StudentCourseGroup> result = new ArrayList<>();
        for (GroupStudent groupStudent : allByCourseId) {
            StudentCourseGroup scg = new StudentCourseGroup();
            Group group = groupMap.get(groupStudent.getGroupId());
            User user = userMap.get(groupStudent.getStudentId());

            scg.setGroupId(group.getId());
            scg.setGroupName(group.getGroupName());

            scg.setStudentId(user.getId());
            scg.setStudentName(user.getName());
            result.add(scg);
        }




        return result;

    }
}
